package com.aidysoft.practice.easypoi.utils;

import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.List;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ItextpdfUtil {

    private static final Integer size = 20;

    /**
     * 功能：创建导出数据的目标文档
     *
     * @param fileName 存储文件的临时路径
     */
    public static Document createDocument(String fileName) {
        File file = new File(fileName);
        FileOutputStream out = null;
        //页面大小
        Rectangle rect = new Rectangle(PageSize.B5.rotate());
        //页面背景色
        rect.setBackgroundColor(BaseColor.ORANGE);

        Document doc = new Document(rect);
        Document document = new Document(rect, 50, 50, 50, 50);
        try {
            out = new FileOutputStream(file);

            //文档属性
            document.addTitle("Title@sample");
            document.addAuthor("Author@rensanning");
            document.addSubject("Subject@iText sample");
            document.addKeywords("Keywords@iText");
            document.addCreator("Creator@iText");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 打开文档准备写入内容  
        document.open();
        return document;
    }

    /**
     * 功能：创造字体格式
     *
     * @param fontname
     * @param size     字体大小
     * @param style    字体风格
     * @param color    字体颜色
     * @return Font
     */
    public static Font createFont(String fontname, float size, int style, BaseColor color) {
        Font font = FontFactory.getFont(fontname, size, style, color);
        return font;
    }

    /**
     * 功能： 返回支持中文的字体
     *
     * @param fontStr 指定字体所在位置
     * @param size    字体大小
     * @param style   字体风格
     * @param color   字体 颜色
     * @return 字体格式
     */
    public static Font createChineseFont(String fontStr, float size, int style, BaseColor color) {
        BaseFont bfChinese = null;
        try {
            bfChinese = BaseFont.createFont(fontStr + ",1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new Font(bfChinese, size, style, color);
    }

    /**
     * 功能： 返回支持中文的字体---微软雅黑
     *
     * @param size  字体大小
     * @param style 字体风格
     * @param color 字体 颜色
     * @return 字体格式
     */
    public static Font createChineseFont(float size, int style, BaseColor color) {
        return createChineseFont("c://windows//fonts//msyhl.ttc", size, style, color);
    }

    /**
     * 功能：向PDF文档中添加短语
     *
     * @param text 内容
     * @param font 内容对应的字体
     * @return phrase 指定字体格式的内容
     */
    public static Phrase createPhrase(String text, Font font) {
        Phrase phrase = new Phrase(text, font);
        return phrase;
    }

    /**
     * 功能：向PDF文档中添加段落
     *
     * @param text 内容
     * @param font 内容对应的字体
     * @return Paraggraph 指定字体格式的内容
     */
    public static Paragraph createParagraph(String text, Font font) {
        Paragraph paragraph = new Paragraph(text, font);
        return paragraph;
    }

    /**
     * 创建链接
     *
     * @param text   内容
     * @param target 链接的名称
     * @return 链接
     */
    public static Anchor setAnchor(String text, String target) {
        Anchor anchorTarget = new Anchor(text);//创建定位符（链接）
        anchorTarget.setName(target);//当单击 target 链接时，它会将您带到文档的第一页
        return anchorTarget;
    }

    /**
     * 功能  创建PDF文档中的章节
     *
     * @param title       章节标题
     * @param chapterNum  章节序列号
     * @param alignment   0表示align=left，1表示align=center
     * @param numberDepth 章节是否带序号 设值=1 表示带序号 1.章节一；1.1小节一...，设值=0表示不带序号
     * @param font        字体格式
     * @return Chapter章节
     */
    public static Chapter createChapter(String title, int chapterNum, int alignment, int numberDepth, Font font) {
        Paragraph chapterTitle = new Paragraph(title, font);
        chapterTitle.setAlignment(alignment);
        Chapter chapter = new Chapter(chapterTitle, chapterNum);
        chapter.setNumberDepth(numberDepth);
        return chapter;
    }

    /**
     * 功能：创建某指定章节下的小节
     *
     * @param chapter     指定章节
     * @param title       小节标题
     * @param font        字体格式
     * @param numberDepth 小节是否带序号 设值=1 表示带序号 1.章节一；1.1小节一...，设值=0表示不带序号
     * @return section在指定章节后追加小节
     */
    public static Section createSection(Chapter chapter, String title, Font font, int numberDepth) {
        Section section = null;
        if (chapter != null) {
            Paragraph sectionTitle = new Paragraph(title, font);
            sectionTitle.setSpacingBefore(20);
            section = chapter.addSection(sectionTitle);
            section.setNumberDepth(numberDepth);
        }
        return section;
    }

    /**
     * 创建表格
     *
     * @param colnum 列数
     * @return 列数为colnum的表格
     */
    public static PdfPTable createPdfPTable(int colnum) {
        PdfPTable table = new PdfPTable(colnum);
        return table;
    }

    /**
     * 创建表格的单元格
     *
     * @param p 短语
     * @return 单元格
     */
    public static PdfPCell createPdfPCell(Phrase p) {
        PdfPCell c = new PdfPCell(p);
        return c;
    }

    /**
     * 设置单元格样式
     *
     * @param cell
     * @return
     */
    public static PdfPCell SetpdfPCellStyle(PdfPCell cell) {
        cell.setFixedHeight(size * 2);//设置高度
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//设置垂直居中
        return cell;
    }

    /**
     * 功能：创建列表
     *
     * @param numbered     设置为true表明想创建一个进行编号的列表
     * @param lettered     设置为true表示列表采用字母进行编号，为false则用数字进行编号
     * @param symbolIndent listItem的缩进量
     * @return list
     */
    public static List createList(boolean numbered, boolean lettered, float symbolIndent) {
        List list = new List(numbered, lettered, symbolIndent);
        return list;
    }

    /**
     * 功能：创建列表中的项
     *
     * @param content 列表项中的内容
     * @param font    字体格式
     * @return listItem
     */
    public static ListItem createListItem(String content, Font font) {
        ListItem listItem = new ListItem(content, font);
        return listItem;
    }

    /**
     * 创建图像
     *
     * @param image 图像文件
     * @return 图像对象
     */
    public static Image createImage(String image) {
        Image im = null;
        try {
            im = Image.getInstance(image);
        } catch (BadElementException ex) {
            Logger.getLogger(ItextpdfUtil.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MalformedURLException ex) {
            Logger.getLogger(ItextpdfUtil.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ItextpdfUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        return im;
    }

    /**
     * 引用链接
     *
     * @param text 内容
     * @param tar  连接到定位符
     * @return 链接
     */
    public static Anchor getAnchor(String text, String tar) {
        Anchor anchor = new Anchor(text);
        anchor.setReference("#" + tar);//设置引用
        return anchor;
    }

    /**
     * 将章节写入到指定的PDF文档中
     *
     * @param chapter
     */
    public static void writeChapterToDoc(Document document, Chapter chapter) {
        try {
            if (document != null) {
                if (!document.isOpen()) document.open();
                document.add(chapter);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 最后关闭PDF文档
     */
    public static void closeDocument(Document document) {
        if (document != null) {
            document.close();
        }
    }

    /**
     * 水印文字
     * @param pdfWriter
     */
    public static void getWaterText(PdfWriter pdfWriter) {
        // 加入水印
        PdfContentByte waterMar = pdfWriter.getDirectContentUnder();
        // 开始设置水印
        waterMar.beginText();
        // 设置水印透明度
        PdfGState gs = new PdfGState();
        // 设置填充字体不透明度为0.4f
        gs.setFillOpacity(0.4f);
        try {
            // 设置水印字体参数及大小                                  (字体参数，字体编码格式，是否将字体信息嵌入到pdf中（一般不需要嵌入），字体大小)
            waterMar.setFontAndSize
                    (
                    BaseFont.createFont(
                            BaseFont.HELVETICA,
                            BaseFont.WINANSI,
                            BaseFont.NOT_EMBEDDED
                    ), 60)
            ;
            // 设置透明度
            waterMar.setGState(gs);
            // 设置水印对齐方式 水印内容 X坐标 Y坐标 旋转角度
            waterMar.showTextAligned
                    (
                            Element.ALIGN_RIGHT,
                            "www.aidySoft.com" ,
                            500, 430, 45
                    );
            // 设置水印颜色
            waterMar.setColorFill(BaseColor.GRAY);
            //结束设置
            waterMar.endText();
            waterMar.stroke();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            waterMar = null;
            gs = null;
        }
    }

    public static void getWaterText
            (
                    String inputFile,
                    String outputFile,
                    String waterMarkName
            ) {
        int interval = -5;
        try {
            PdfReader reader = new PdfReader(inputFile);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
                    outputFile));

            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            Rectangle pageRect = null;
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.3f);
            gs.setStrokeOpacity(0.4f);
            int total = reader.getNumberOfPages() + 1;

            JLabel label = new JLabel();
            FontMetrics metrics;
            int textH = 0;
            int textW = 0;
            label.setText(waterMarkName);
            metrics = label.getFontMetrics(label.getFont());
            textH = metrics.getHeight();
            textW = metrics.stringWidth(label.getText());

            PdfContentByte under;
            for (int i = 1; i < total; i++) {
                pageRect = reader.getPageSizeWithRotation(i);
                under = stamper.getOverContent(i);
                under.saveState();
                under.setGState(gs);
                under.beginText();
                under.setFontAndSize
                        (
                                BaseFont.createFont(
                                        BaseFont.HELVETICA,
                                        BaseFont.WINANSI,
                                        BaseFont.NOT_EMBEDDED
                                ), 20)
                ;
                // 水印文字成30度角倾斜
                //你可以随心所欲的改你自己想要的角度
                for (int height = interval + textH; height < pageRect.getHeight();
                     height = height + textH * 5) {
                    for (int width = interval + textW; width < pageRect.getWidth() + textW;
                         width = width + textW * 2) {
                        under.showTextAligned(
                                Element.ALIGN_LEFT
                                , waterMarkName,
                                width - textW,
                                height - textH,
                                30);
                    }
                }
                // 添加水印文字
                under.endText();
            }
            //说三遍
            //一定不要忘记关闭流
            //一定不要忘记关闭流
            //一定不要忘记关闭流
            stamper.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 水印图片
     * @param pdfWriter
     */
    public static void getWaterPic(PdfWriter pdfWriter) {
        // 加入水印
        PdfContentByte waterMar = pdfWriter.getDirectContentUnder();
        // 开始设置水印
        waterMar.beginText();
        // 设置水印透明度
        PdfGState gs = new PdfGState();
        // 设置笔触字体不透明度为0.4f
        gs.setStrokeOpacity(0.4f);
        try {
            Image image = Image.getInstance("d:\\1.jpg");
            // 设置坐标 绝对位置 X Y
            image.setAbsolutePosition(150, -50);
            // 设置旋转弧度
            image.setRotation(30);// 旋转 弧度
            // 设置旋转角度
            image.setRotationDegrees(45);// 旋转 角度
            // 设置等比缩放
            image.scalePercent(90);// 依照比例缩放
            // image.scaleAbsolute(200,100);//自定义大小
            // 设置透明度
            waterMar.setGState(gs);
            // 添加水印图片
            waterMar.addImage(image);
            // 设置透明度
            waterMar.setGState(gs);
            //结束设置
            waterMar.endText();
            waterMar.stroke();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            waterMar = null;
            gs = null;
        }
    }


    public static void getWaterPic
            (
                    String inputFile,
                    String outputFile
            ) {

        try {
            PdfReader reader = new PdfReader(inputFile);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
                    outputFile));

            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.3f);
            gs.setStrokeOpacity(0.4f);
            int total = reader.getNumberOfPages() + 1;


            PdfContentByte under;
            for (int i = 1; i < total; i++) {
                Rectangle pageRect = reader.getPageSizeWithRotation(i);
                under = stamper.getOverContent(i);

                Image image = Image.getInstance("d:\\1.jpg");
                // 设置坐标 绝对位置 X Y
                image.setAbsolutePosition(150, -50);
                // 设置旋转弧度
                image.setRotation(30);// 旋转 弧度
                // 设置旋转角度
                image.setRotationDegrees(45);// 旋转 角度
                // 设置等比缩放
                image.scalePercent(90);// 依照比例缩放
                // image.scaleAbsolute(200,100);//自定义大小
                // 设置透明度
                under.setGState(gs);
                // 添加水印图片
                under.addImage(image);
                // 设置透明度
                under.setGState(gs);
                //结束设置
                under.endText();
                under.stroke();


            }
            //说三遍
            //一定不要忘记关闭流
            //一定不要忘记关闭流
            //一定不要忘记关闭流
            stamper.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public static void main(String args[]) {
        String fileName = "D:\\testTable3.pdf";
        ItextpdfUtil pdf = new ItextpdfUtil();

        Font chapterFont = createChineseFont(20, Font.BOLD, new BaseColor(0, 0, 255));//文章标题字体
        Font sectionFont = createChineseFont(16, Font.BOLD, new BaseColor(0, 0, 255));//文章小节字体
        Font textFont = createChineseFont(10, Font.NORMAL, new BaseColor(0, 0, 0));//小节内容字体

        Document document = pdf.createDocument(fileName);//打开文档

        //创建章节
        Chapter chapter = createChapter("章1", 1, 1, 0, chapterFont);
        Section section1 = createSection(chapter, "节1.1", sectionFont, 0);
        Phrase text1 = createPhrase("Hello,欢迎使用iText", textFont);
        section1.add(text1);
        //创建定位符
        Anchor anchor1 = setAnchor("This is an anchor", "Back to Top");
        Paragraph paragraph1 = createParagraph("这是一段段落", sectionFont);
        paragraph1.add(anchor1);
        section1.add(paragraph1);

        Section section2 = createSection(chapter, "节1.2", sectionFont, 0);
        Phrase text2 = createPhrase("列表：", textFont);
        text2.setLeading(20); //上边距
        section2.add(text2);

        //创建列表
        List list = createList(true, false, 20);
        String tmp = "文档是 PDF 文档的所有元素的容器";
        ListItem listItem1 = createListItem(tmp, textFont);
        ListItem listItem2 = createListItem("列表2", textFont);
        list.add(listItem1);
        list.add(listItem2);
        //创建图像
        Image i = createImage("D:\\1.jpg");
        list.add(i);
        section2.add(list);

        Section section3 = createSection(chapter, "节1.3", sectionFont, 0);
        Phrase text3 = createPhrase("表格：", textFont);
        section3.add(text3);

        //创建表格
        PdfPTable table = createPdfPTable(3);
        table.addCell(i);
        table.addCell(text3);
        table.addCell("列3");
        table.addCell(text2);
        section3.add(table);

        Section section4 = createSection(chapter, "节1.4", sectionFont, 0);
        Phrase text4 = createPhrase("定位符：", textFont);
        section4.add(text4);
        //引用定位符
        Anchor anchor2 = getAnchor("Back to Top", "Back to Top");
        section4.add(anchor2);

        //写入一整章内容
        pdf.writeChapterToDoc(document, chapter);

        //关闭文档
        pdf.closeDocument(document);
    }
}


class ProcessPDF {

    public static void main(String[] args) {
        try {
           /* java.util.List<InputStream> pdfs = new ArrayList<InputStream>();
            pdfs.add(new FileInputStream("D:\\mark1111upGRAY.pdf"));
            pdfs.add(new FileInputStream("D:\\mark2222upGRAY.pdf"));
            OutputStream output = new FileOutputStream("D:\\789.pdf");
            concatPDFs(pdfs, output, true);
*/
            ProcessPDF.addPdfImgMark("D:\\testTable3.pdf",
                    "D:\\mark1111upGRAY.pdf",
                    "D:\\1.jpg",
                    300,350);
            ProcessPDF.addPdfTextMark("D:\\testTable3.pdf",
                    "D:\\mark2222upGRAY.pdf", "水印dddd文字", 300,
                    350);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static File mergeFiles(String[] files, String result, boolean smart) throws IOException, DocumentException {
        Document document = new Document();
        PdfCopy copy;
        if (smart)
            copy = new PdfSmartCopy(document, new FileOutputStream(result));
        else
            copy = new PdfCopy(document, new FileOutputStream(result));
        document.open();
        PdfReader[] reader = new PdfReader[files.length];
        for (int i = 0; i < files.length; i++) {
            reader[i] = new PdfReader(files[i]);
            copy.addDocument(reader[i]);
            copy.freeReader(reader[i]);
            reader[i].close();
        }
        document.close();
        return new File(result);
    }

    /**
     * 合并pdf
     *
     * @param streamOfPDFFiles
     * @param outputStream
     * @param paginate
     */
    public static void concatPDFs(java.util.List<InputStream> streamOfPDFFiles,
                                  OutputStream outputStream, boolean paginate) {

        Document document = new Document();
        try {
            java.util.List<InputStream> pdfs = streamOfPDFFiles;
            java.util.List<PdfReader> readers = new ArrayList<PdfReader>();
            int totalPages = 0;
            Iterator<InputStream> iteratorPDFs = pdfs.iterator();

            // Create Readers for the pdfs.
            while (iteratorPDFs.hasNext()) {
                InputStream pdf = iteratorPDFs.next();
                PdfReader pdfReader = new PdfReader(pdf);
                readers.add(pdfReader);
                totalPages += pdfReader.getNumberOfPages();
            }
            // Create a writer for the outputstream
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);

            document.open();
            BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
                    BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
            // data

            PdfImportedPage page;
            int currentPageNumber = 0;
            int pageOfCurrentReaderPDF = 0;
            Iterator<PdfReader> iteratorPDFReader = readers.iterator();

            // Loop through the PDF files and add to the output.
            while (iteratorPDFReader.hasNext()) {
                PdfReader pdfReader = iteratorPDFReader.next();

                // Create a new page in the target for each source page.
                while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
                    document.newPage();
                    pageOfCurrentReaderPDF++;
                    currentPageNumber++;
                    page = writer.getImportedPage(pdfReader,
                            pageOfCurrentReaderPDF);
                    cb.addTemplate(page, 0, 0);

                    // Code for pagination.
                    if (paginate) {
                        cb.beginText();
                        cb.setFontAndSize(bf, 9);
                        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
                                        + currentPageNumber + " of " + totalPages, 520,
                                5, 0);
                        cb.endText();
                    }
                }
                pageOfCurrentReaderPDF = 0;
            }
            outputStream.flush();
            document.close();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document.isOpen())
                document.close();
            try {
                if (outputStream != null)
                    outputStream.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     *
     * <br>
     * <p>
     * Description: 给pdf文件添加水印 <br>
     * <p><br/>
     * <p>
     *
     * @param InPdfFile
     *            要加水印的原pdf文件路径
     * @param outPdfFile
     *            加了水印后要输出的路径
     * @param markImagePath
     *            水印图片路径
     * @param imgWidth
     *            图片横坐标
     * @param imgHeight
     *            图片纵坐标
     * @throws Exception

     */
    public static void addPdfImgMark(String InPdfFile, String outPdfFile, String markImagePath,int imgWidth, int imgHeight) throws Exception {
        PdfReader reader = new PdfReader(InPdfFile, "PDF".getBytes());
        PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfFile)));

        PdfContentByte under;

        PdfGState gs1 = new PdfGState();
        gs1.setFillOpacity(0.3f);// 透明度设置

        Image img = Image.getInstance(markImagePath);// 插入图片水印

        img.setAbsolutePosition(imgWidth, imgHeight); // 坐标
        img.setRotation(-20);// 旋转 弧度
        img.setRotationDegrees(45);// 旋转 角度
        // img.scaleAbsolute(200,100);//自定义大小
        // img.scalePercent(50);//依照比例缩放

        int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
        for(int i = 1; i <= pageSize; i++) {
            under = stamp.getUnderContent(i);// 水印在之前文本下
            // under = stamp.getOverContent(i);//水印在之前文本上
            under.setGState(gs1);// 图片水印 透明度
            under.addImage(img);// 图片水印
        }

        stamp.close();// 关闭
        // // 删除不带水印文件
//		File tempfile = new File(InPdfFile);
//		if(tempfile.exists()) {
//			tempfile.delete();
//		}

    }

    /**
     *
     * <br>
     * <p>
     * Description: 给pdf文件添加水印<br>
     *
     * @param InPdfFile
     *            要加水印的原pdf文件路径
     * @param outPdfFile
     *            加了水印后要输出的路径
     * @param textMark
     *            水印文字
     * @param textWidth
     *            文字横坐标
     * @param textHeight
     *            文字纵坐标
     * @throws Exception
     */
    public static void addPdfTextMark(String InPdfFile, String outPdfFile, String textMark,int textWidth,
                                      int textHeight) throws Exception {
        PdfReader reader = new PdfReader(InPdfFile, "PDF".getBytes());
        PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfFile)));

        PdfContentByte under;

        BaseFont font = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", "Identity-H", true);// 使用系统字体

        int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
        for(int i = 1; i <= pageSize; i++) {
            under = stamp.getUnderContent(i);// 水印在之前文本下
            // under = stamp.getOverContent(i);//水印在之前文本上
            under.beginText();
            under.setColorFill(BaseColor.GRAY);// 文字水印 颜色
            under.setFontAndSize(font, 38);// 文字水印 字体及字号
            under.setTextMatrix(textWidth, textHeight);// 文字水印 起始位置
            under.showTextAligned(Element.ALIGN_CENTER, textMark, textWidth, textHeight, 45);
            under.endText();
        }

        stamp.close();// 关闭
    }


}